/*
* button: gpio5
* led: gpio2
* mqtt
* sntp
*/

#include "mgos.h"
#include "mgos_mqtt.h"
#include "mgos_rpc.h"
#include "mgos_system.h"
//#include "mg_str.h"
// #include "string.h"

#define led 2
#define button 5
#define LED_ON 0
#define LED_OFF 1

// #define DAY 7
// #define NIGHT 19
static void cb_sub_mqtt(struct mg_connection *nc, const char *topic,
                        int topic_len, const char *msg, int msg_len,
                        void *userdata);
int c = 0;
int c_0 = 0;

// 白班，夜班
bool is_day = false;
bool is_day_old = false;
bool is_night = false;
bool hi = true;

int DAY = 7;
int NIGHT = 19;

bool read_once = true;
bool time_is_ok = false;

char m_time[19];
//char *topic = "";

static void cb_button_5(int pin, void *arg)
{
  c++;
  LOG(LL_INFO, ("btn %d fired，%d", pin, c));
  printf("btn %d fired，%d", pin, c);

  (void)arg;
}
// 回调：wifi 事件
static void cb_wifi(int ev, void *evd, void *arg)
{
  switch (ev)
  {
  case MGOS_WIFI_EV_STA_DISCONNECTED:
    LOG(LL_INFO, ("WiFi STA disconnected %p", arg));
    mgos_gpio_write(led, LED_OFF);
    break;
  case MGOS_WIFI_EV_STA_CONNECTING:
    LOG(LL_INFO, ("WiFi STA connecting %p", arg));
    break;
  case MGOS_WIFI_EV_STA_CONNECTED:
    LOG(LL_INFO, ("WiFi STA connected %p", arg));

    break;
  case MGOS_WIFI_EV_STA_IP_ACQUIRED:
    LOG(LL_INFO, ("WiFi STA IP acquired %p", arg));
    mgos_gpio_write(led, LED_ON);
    break;
  }
  (void)evd;
  (void)arg;
}
// util
void myPrint(char *buffer, const char *format, ...)
{
  // char buffer[256];
  va_list args;
  va_start(args, format);
  vsnprintf(buffer, 19, format, args);
  va_end(args);
}
// 回调： 1秒定时器
static void cb_timer_1s(void *arg)
{
  // 取时间
  time_t now = (time_t)mg_time() + 8 * 3600;
  struct tm *t = localtime(&now);
  myPrint(m_time, "%d-%d-%d %d:%d:%d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,
          t->tm_min, t->tm_sec);
  // debug
  if (t->tm_sec % 10 == 0)
  {
    printf("now is %s\n", m_time);
  }
  // 时间正确
  if (t->tm_year > 1970)
    time_is_ok = true;
  else
    time_is_ok = false;

  // 判断日夜转变
  if (time_is_ok)
  {
    if (t->tm_hour >= DAY && t->tm_hour < NIGHT)
    {
      is_day = true;
      is_night = false;
    }
    if (t->tm_hour == NIGHT)
    {
      is_day = false;
      is_day_old = false;
      is_night = true;
    }
    // 计数清零
    if (!is_day_old && is_day)
    {
      c = 0;
      c_0 = 0;
      is_day_old = is_day;
    }
  }
  (void)arg;
}
// 回调： mqtt定时发送
static void cb_timer_mqtt(void *arg)
{
  if (!time_is_ok)
    return;
  char id[50];

  strcpy(id, mgos_sys_config_get_device_id());
  mgos_mqtt_pubf("/xy/events", 1, false, "{num:%d, id:%Q, t:%Q}", c, id, m_time);
  (void)arg;
}

void rpc_response(struct mg_rpc_request_info *ri, char *json_fmt, ...)
{
  struct mbuf fb;
  struct json_out out = JSON_OUT_MBUF(&fb);
  mbuf_init(&fb, 256);
  memset(fb.buf, 0, 256);
  printf("json_fmt:%s\n", json_fmt);
  va_list ap;
  va_start(ap, json_fmt);
  json_vprintf(&out, json_fmt, ap);
  va_end(ap);
  printf("out is:%s, len is:%d\n", fb.buf, fb.len);
  mgos_rpc_send_response(ri, fb.buf);
  //(void)ri;
  // free
  mbuf_free(&fb);
}

// 回调：rpc
static void cb_rpc_cmd(struct mg_rpc_request_info *ri, const char *args,
                       const char *src, void *user_data)
{
  bool reboot = false;
  int new_sum = 0;
  printf("rpc args is: %s\n", args);
  if (json_scanf(args, strlen(args), "{reboot: %B}", &reboot) == 1)
  {
    printf("reboot,\n");
    rpc_response(ri, "{info: %Q}", "rebooting...");
    mgos_system_restart();
  }
  if (json_scanf(args, strlen(args), "{sum: %d}", &new_sum) == 1)
  {
    c = new_sum;
    c_0 = new_sum;
    rpc_response(ri, "{sum: %d}", c);
  }
  if (ri != NULL)
  {
    ri = NULL;
  }

  (void)src;
  (void)user_data;
}

// 回调：mqtt订阅
static void cb_sub_mqtt(struct mg_connection *nc, const char *topic,
                        int topic_len, const char *msg, int msg_len,
                        void *user_data)
{
  if (msg_len == 0)
    return;
  int num = 0;

  //char *ts = calloc(19, sizeof(char));
  char *_msg = calloc(256, sizeof(char));
  char *ts = NULL;
  if (_msg == NULL)
  {
    printf("mem alloc failure\n");
    return;
  }
  memset(_msg, 0, 256);
  memcpy(_msg, msg, msg_len);
  printf("_msg is: %s, len: %d, str_len:%d\n", _msg, msg_len, strlen(_msg));

  if (json_scanf(_msg, strlen(_msg), "{num: %d, tm: %Q}", &num, &ts) == 2)
  {
    struct tm _tm;
    memset(&_tm, 0, sizeof(struct tm));

    strptime(ts, "%Y-%m-%d %H:%M:%S", &_tm);
    _tm.tm_year += 1900;
    _tm.tm_mon++;

    printf("%d-%d-%d %d:%d:%d\n", _tm.tm_year, _tm.tm_mon, _tm.tm_mday, _tm.tm_hour, _tm.tm_min, _tm.tm_sec);
    // 判断时间是否超过太久
  }
  else
  {
    printf("no match\n");
  }
  if (ts != NULL)
  {
    free(ts);
    printf("ts is freed\n");
  }
  free(_msg);

  (void)nc;
  (void)topic;
  (void)topic_len;
  (void)user_data;
}

// mqtt handler
static void handler_hi(struct mg_connection *nc, int ev, void *ev_data,
                       void *user_data)
{
  if (ev == MG_EV_MQTT_CONNACK)
  {
    // 发布： hi
    char *msg = "hi";
    mgos_mqtt_pub(mgos_sys_config_get_device_id(), msg, strlen(msg), 1, false);
    // 订阅
    mgos_mqtt_sub(mgos_sys_config_get_device_id(), cb_sub_mqtt, NULL);
  }
  (void)nc;
  (void)ev_data;
  (void)user_data;
}

// main
enum mgos_app_init_result mgos_app_init(void)
{
  LOG(LL_INFO, ("Hi, wellcome"));
  // 信号灯脚输出模式
  mgos_gpio_set_mode(led, MGOS_GPIO_MODE_OUTPUT);
  // 按键中断
  mgos_gpio_set_button_handler(button, MGOS_GPIO_PULL_UP, MGOS_GPIO_INT_EDGE_POS, 200, cb_button_5, NULL);

  // wifi 事件
  mgos_event_add_group_handler(MGOS_WIFI_EV_BASE, cb_wifi, NULL);
  // 1秒定时器
  mgos_set_timer(1000, MGOS_TIMER_REPEAT, cb_timer_1s, NULL);

  // 60秒定时器，发送mqtt
  mgos_set_timer(60 * 1000, MGOS_TIMER_REPEAT, cb_timer_mqtt, NULL);

  // rpc
  mgos_rpc_add_handler("cmd", cb_rpc_cmd, NULL);

  // hi
  mgos_mqtt_add_global_handler(handler_hi, NULL);

  return MGOS_APP_INIT_SUCCESS;
}
